﻿using AutoMapper;
using Core.Utility.Attributes;
using Core.Utility.Extendsions.Validation;
using Core.Utility.Helper;
using Newtonsoft.Json;
using NPOI.Util;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Runtime.CompilerServices;
using System.Text;

namespace Dto.Core
{
    /// <summary>
    /// 基础Dto
    /// </summary>
    public class BaseDto : INotifyPropertyChanged, IDataErrorInfo
    {
        /// <summary>
        /// 默认构造
        /// </summary>
        public BaseDto()
        {
            DtoMode = DtoMode.Select;            
        }

        #region Dto模式

        /// <summary>
        /// Dto模式
        /// </summary>
        private DtoMode _dtoMode = DtoMode.Select;

        /// <summary>
        /// Dto模式
        /// </summary>
        [JsonProperty("dto_mode")]
        [DataColumn(Ignore = true)]
        public DtoMode DtoMode
        {
            get { return _dtoMode; }
            set { SetProperty(ref _dtoMode, value); }
        }
        #endregion Dto模式 

        #region 验证结果信息

        /// <summary>
        /// 验证结果信息
        /// </summary>
        private ValidationResultInfo? _validationResultInfo = new ValidationResultInfo();

        /// <summary>
        /// 验证结果信息
        /// </summary>
        [JsonIgnore]
        [DataColumn(Ignore = true)]
        public ValidationResultInfo? ValidationResultInfo
        {
            get { return _validationResultInfo; }
            set { SetProperty(ref _validationResultInfo, value); }
        }

        #endregion 验证结果信息 

        /// <summary>
        /// 属性变更
        /// </summary>
        public event PropertyChangedEventHandler? PropertyChanged;

        /// <summary>
        /// 实现通知更新
        /// </summary>
        /// <param name="propertyName"></param>
        public void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (!string.IsNullOrEmpty(propertyName))
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        /// <summary>
        /// 设置属性，实现通知
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="storage"></param>
        /// <param name="value"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
        {
            if (EqualityComparer<T>.Default.Equals(storage, value))
            {
                return false;
            }

            storage = value;
            OnPropertyChanged(propertyName);            
            return true;
        }

        /// <summary>
        /// 设置属性，实现通知
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="storage"></param>
        /// <param name="value"></param>
        /// <param name="onChanged"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        protected virtual bool SetProperty<T>(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = "")
        {
            if (EqualityComparer<T>.Default.Equals(storage, value))
            {
                return false;
            }

            storage = value;
            onChanged?.Invoke();
            OnPropertyChanged(propertyName);
            return true;
        }

        #region 错误信息相关验证.

        #region 自定义错误信息
        /// <summary>
        /// 自定义验证错误信息
        /// Key => propertyName;
        /// Value => ErrorMessage;
        /// </summary>
        private readonly Dictionary<string, ICollection<string>> _customValidationErrorList = new Dictionary<string, ICollection<string>>();

        /// <summary>
        /// 清除自定义错误信息
        /// </summary>
        public void ClearCustomValidationErrorList()
        {
            _customValidationErrorList.Clear();
        }

        /// <summary>
        /// 添加错误信息，错误列表将被替换
        /// </summary>
        /// <param name="errorMessageList">错误信息列表</param>
        /// <param name="propertyName">属性名称</param>
        public void AddCustomValidationError(ICollection<string> errorMessageList, [CallerMemberName] string propertyName = "")
        {
            if (!string.IsNullOrEmpty(propertyName))
            {
                if (_customValidationErrorList.ContainsKey(propertyName))
                {
                    _customValidationErrorList[propertyName] = errorMessageList;
                }
                else
                {
                    _customValidationErrorList.Add(propertyName, errorMessageList);
                }
            }
        }

        /// <summary>
        /// 添加错误信息，在错误列表的基础上继续追加
        /// </summary>
        /// <param name="errorMessage"></param>
        /// <param name="propertyName"></param>
        public void AddCustomValidationError(string errorMessage, [CallerMemberName] string propertyName = "")
        {
            if (!string.IsNullOrEmpty(propertyName))
            {
                if (_customValidationErrorList.ContainsKey(propertyName))
                {
                    _customValidationErrorList[propertyName].Add(propertyName);
                }
                else
                {
                    _customValidationErrorList.Add(propertyName, new List<string>() { errorMessage });
                }
            }
        }

        /// <summary>
        /// 移除错误信息
        /// </summary>
        /// <param name="propertyName"></param>
        public void RemoveCustomValidationError([CallerMemberName] string propertyName = "")
        {
            if (!string.IsNullOrEmpty(propertyName))
            {
                if (_customValidationErrorList.ContainsKey(propertyName))
                {
                    _customValidationErrorList[propertyName].Remove(propertyName);
                }
            }
        }
        #endregion 自定义错误信息


        /// <summary>
        /// 错误
        /// </summary>
        [JsonIgnore]
        [DataColumn(Ignore = true)]
        public string Error
        {
            get
            {
                string res = "";
                var validRes = ValidResult();
                if (!validRes.IsValid)
                {
                    res = validRes.ErrorMessages.ToString();
                }
                if (_customValidationErrorList?.Count > 0 && _customValidationErrorList.Where(p => p.Value.Count() > 0).Count() > 0)
                {
                    StringBuilder errorMessageStringBuilder = new StringBuilder();
                    foreach (var errorItem in _customValidationErrorList.Values)
                    {
                        foreach (var error in errorItem)
                        {
                            errorMessageStringBuilder.AppendLine(error);
                        }
                    }
                }
                return res;
            }
        }

        /// <summary>
        /// 自定义验证，用于某些特殊场景下做数据校验
        /// </summary>
        public virtual Dictionary<string, ICollection<string>> CustomValidation()
        {
            Dictionary<string, ICollection<string>> errorDictionary = new Dictionary<string, ICollection<string>>();
            return errorDictionary;
        }

        /// <summary>
        /// 数据有效验证结果
        /// </summary>
        /// <returns></returns>
        public virtual ValidationExtensionsResult ValidResult()
        {
            ValidationExtensionsResult result = ValidatetionExtensions.ValidResult(this);
            var errorDictionary = _customValidationErrorList;
            var customValidationErrorDictionary = CustomValidation();
            if(customValidationErrorDictionary != null && errorDictionary.Count > 0)
            {
                foreach(var keyValue in customValidationErrorDictionary)
                {
                    if (errorDictionary.ContainsKey(keyValue.Key))
                    {
                        var list = errorDictionary[keyValue.Key].ToList();
                        //合并、去重
                        list.AddRange(keyValue.Value);
                        list = list.Distinct().ToList();
                        errorDictionary[keyValue.Key] = list;
                    }
                    else
                    {
                        errorDictionary.Add(keyValue.Key, keyValue.Value);
                    }
                }
            }

            //进行自定义错误校验信息补充
            if (errorDictionary?.Count > 0 && errorDictionary.Where(p => p.Value.Count() > 0).Count() > 0)
            {
                result.IsValid = false;
                List<ErrorMember> errorMemberList = new List<ErrorMember>();
                foreach (var errorItem in _customValidationErrorList)
                {
                    foreach (var error in errorItem.Value)
                    {
                        var errorMember = new ErrorMember();
                        errorMember.ErrorMemberName = errorItem.Key;
                        errorMember.ErrorMessage = error;
                        errorMemberList.Add(errorMember);
                    }
                }
                if (result.ErrorMessages != null && result.ErrorMessages.Count() > 0)
                {
                    result.ErrorMembers?.AddRange(errorMemberList);
                }
                else
                {
                    result.ErrorMembers = errorMemberList;
                }
            }
            ValidationResultInfo = new ValidationResultInfo(result.IsValid);
            ValidationResultInfo.ErrorInfo = result.ErrorMessages;
            return result;
        }

        /// <summary>
        /// 数据有效验证结果
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual ValidationExtensionsResult ValidResult(object obj)
        {
            return ValidatetionExtensions.ValidResult(obj);
        }

        /// <summary>
        /// 字段校验
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        [DataColumn(Ignore = true)]
        public virtual string this[string columnName]
        {
            get
            {
                var vc = new ValidationContext(this, null, null);
                vc.MemberName = columnName;
                var res = new List<ValidationResult>();
                var result = Validator.TryValidateProperty(this.GetType()?.GetProperty(columnName)?.GetValue(this, null), vc, res);
                ValidResult();
                if (res.Count > 0)
                {
                    //仅返回第一条错误信息
                    ValidationResult? errorVR = res.FirstOrDefault();
                    if(errorVR != null)
                    {
                        return errorVR.ErrorMessage.GetValueOrDefault();
                    }
                    else
                    {
                        return string.Empty;
                    }//return string.Join(Environment.NewLine, res.Select(r => r.ErrorMessage).ToArray());
                }
                return string.Empty;
            }
        }

        #region 自定义校验示例
        //private string? _sampleValidateField;
        //[Required]
        //[ValidateRulesStringLength(60)]
        //[DisplayName("示例验证字段")]
        //[CustomValidation(typeof(BaseModel), nameof(SampleValidate))]
        //public string SampleValidateField
        //{
        //    get { return _sampleValidateField; }
        //    set { _sampleValidateField = value; RaisePropertyChanged(nameof(SampleValidateField)); }
        //}

        ///// <summary>
        ///// 自定义验证示例规则
        ///// </summary>
        ///// <param name="obj"></param>
        ///// <param name="context"></param>
        ///// <returns></returns>
        //public static ValidationResult SampleValidate(object obj, ValidationContext context)
        //{
        //    var model = (BaseModel)context.ObjectInstance;
        //    if (model.Error != model.SampleValidateField)
        //    {
        //        return new ValidationResult("这是一个示例验证字段的错误信息",
        //            new List<string> { nameof(SampleValidateField), "某个错误属性名称" });
        //    }
        //    //验证通过
        //    return ValidationResult.Success;
        //}
        #endregion 自定义校验示例

        #endregion 错误信息相关验证
    }

    /// <summary>
    /// 基础Dto
    /// </summary>
    public interface IBaseDto
    {
        #region Dto模式

        /// <summary>
        /// Dto模式
        /// </summary>
        [JsonProperty("dto_mode")]
        public DtoMode DtoMode
        {
            get;set;
        }

        #endregion Dto模式 

        /// <summary>
        /// 验证结果
        /// </summary>
        public ValidationResultInfo? ValidationResultInfo { get; set; }


        /// <summary>
        /// 错误
        /// </summary>
        public string Error
        {
            get;
        }

        /// <summary>
        /// 数据有效验证结果
        /// </summary>
        /// <returns></returns>
        public ValidationExtensionsResult ValidResult();

        /// <summary>
        /// 数据有效验证结果
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public ValidationExtensionsResult ValidResult(object obj);
    }
}